package revisaosistematica;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author claudiane
 */
public class Extracao {

    //variável que armazena o número total de documentos
    public static int totalDocs;
    
    //vetor que armazena a maxima frequencia do titulo
    public static ArrayList<Integer> vetorMaxFreq = new ArrayList<Integer>();

    //vetor que armazena a maxima frequencia do abstract
    public static ArrayList<Integer> vetorMaxFreqAbs = new ArrayList<Integer>();
    
    public static int getTotalDocs() {
        return totalDocs;
    }

    public static void setTotalDocs(int total) {
        totalDocs = total;
    }
    
    public static ArrayList<Integer> getVetorMaxFreq() {
        return vetorMaxFreq;
    }

    public static void setVetorMaxFreq(ArrayList<Integer> maxFreq) {
        Extracao.vetorMaxFreq = maxFreq;
    }
    
    public static ArrayList<Integer> getVetorMaxFreqAbs() {
        return vetorMaxFreqAbs;
    }

    public static void setVetorMaxFreqAbs(ArrayList<Integer> maxFreqAbs) {
        Extracao.vetorMaxFreqAbs = maxFreqAbs;
    }

    //Obtem o conteudo do arquivo passado por parametro
    public static String getCodFile(String file) throws FileNotFoundException, IOException {

        File fi = new File(file);
        FileInputStream fis = new FileInputStream(fi);
        byte[] b = new byte[(int) fi.length()];
        fis.read(b);
        fis.close();
        return new String(b);

    }

    //Obtem o conteudo do arquivo lido
    public static String getContentFile() throws FileNotFoundException, IOException {

        //para ler todos os arquivos
        File arquivos[];
        File diretorio = new File("BaseDados/");
        arquivos = diretorio.listFiles();

        //variavel que armazena todos os documentos
        String todos = null;
        for (int i = 0; i < arquivos.length; i++) {

            File fi = new File(arquivos[i].toString());
            FileInputStream fis = new FileInputStream(fi);
            byte[] b = new byte[(int) fi.length()];
            fis.read(b);
            todos = todos + new String(b);
            fis.close();
        }
        return todos;

    }

    // Recebe documento e padrao que deseja encontrar 
    // Retorna a string com o padrao encontrado ou retorna vazio se nao encontrar o padrão
    public static String getPattern(String documento, String pattern) {
    	
        //Pattern representa uma string compilada que recebe o padrao que deseja buscar
        Pattern padrao = Pattern.compile(pattern, Pattern.DOTALL);
        
        //procura o padrao passado no documento
        Matcher matcher = padrao.matcher(documento);
        String result = "";

        //percorre todo o martcher enquanto encontrar o padrão e retorna tudo encontrado
        while (matcher.find()) {
            result += matcher.group() + "\n";
        }

        return result;
    }

    //Obtem o primeiro padrao encontrado dentro da string passada
    public static String getFirstPattern(String codPage, String pattern) {
        Pattern padrao = Pattern.compile(pattern, Pattern.DOTALL);
        Matcher matcher = padrao.matcher(codPage);
        String result = "";

        while (matcher.find()) {
            result = matcher.group();
            return result;
        }


        return result;
    }

    //Obtem o titulo da publicação
    public static String getTitle(String documento) {

        //busca o padrão do título dos artigos
        String title = getFirstPattern(documento, "title = \\{[^\\}]*");
        title = title.replaceAll("title = \\{", "");
        title = title.replaceAll("\n", " ");
        title = title.replaceAll("\t", " ");
        title = title.replaceAll(" +", " ");

        // System.out.println("Titulo "+title);
        return title;
    }

    //Obtem o abstract do artigo
    public static String getAbstract(String documento) {

        //busca o padrão do abstract no artigo
        String abs = getPattern(documento, "abstract = \\{[^\\}]*");
        abs = abs.replaceAll("abstract = \\{", "");
        //System.out.println("Abs "+abs);

        return abs;
    }

    //Obtem as palavras chave abstract do artigo
    public static String getKeyWords(String documento) {

        //busca o padrão do abstract no artigo
        String key = getPattern(documento, "keywords = \\{[^\\}]*");
        key = key.replaceAll("keywords = \\{", "");

        return key;
    }


    //Obtem todos os campos juntos, titulo, abstract e keywords
    public static String getResultAbsKey(String documento) {

        StringBuilder sb = new StringBuilder("");

        String abs = getAbstract(documento);
        if (abs == null || abs.trim().equals("")) {
            Util.escreverSaidaAbs(documento);

        } else {

            sb.append(abs);
            sb.append(getKeyWords(documento));

        }
        String result = new String(sb);

        //System.out.println("Tudo "+result);

        return result;
    }

    public static String getPreProcessaDoc(String documento) {

        //substitui sinais de pontuação e caracteres especiais do documento por um espaço em branco
        documento = documento.replaceAll("[&%+\"“”(;,):\\./-]", " ");
        documento = documento.replaceAll("<>]\\[?\\'\\’\\<", " ");
        documento = documento.replaceAll("\t", "");
        documento = documento.replaceAll("'", "");
        documento = documento.replace("’", " ");
        documento = documento.replace("‘", " ");
        documento = documento.replaceAll("[),\\.’']$", " ");

        documento = documento.replaceAll(":punct:", " ");

        //substitui 1 ou mais espaços em branco por apenas 1 espaço.
        documento = documento.replaceAll(" +", " ");

        return documento;
    }

    //Obtem cada documento separado 
    public static void getDocSeparado(String documento, HashToken ht, String consulta) throws FileNotFoundException, IOException {

        //vetor para armazenar os artigos que foram excluidos
        ArrayList<String> vetorAbsExcluidos = new ArrayList<String>();
        ArrayList<String> vetorTitleExcluidos = new ArrayList<String>();
        ArrayList<String> vetorKeyExcluidos = new ArrayList<String>();

        //variavel que controla qual é a maxima frequencia do documento
        int maxFreq;
        int maxFreqAbs;

        //instancia a hash que contem as StopWords
        HashStopWords hst = new HashStopWords();
        hst.addStopWordsHash();

        //Divide o documento no inicio de cada artigo
        String[] arrayDocs = documento.split("@ARTICLE|@INPROCEEDINGS|@OTHER");
        documento = null;
        
        String[] expressoesConsulta = extrairExpressoes(consulta);
        
        //variavel que controla os artigos validos
        int j = -1;
        for (int i = 0; i < arrayDocs.length; i++) {

        	if (arrayDocs[i].trim().equals("")) {
        		continue;
        	}

        	String titulo = getTitle(arrayDocs[i]);
            String abs = getAbstract(arrayDocs[i]);
            String key = getKeyWords(arrayDocs[i]);

            if (titulo.equals("")) {
                vetorTitleExcluidos.add(arrayDocs[i]);
                continue;
            }
            if (abs.equals("")) {
                vetorAbsExcluidos.add(arrayDocs[i]);
                continue;
            }
            if (key.equals("")) {
                vetorKeyExcluidos.add(arrayDocs[i]);
                continue;
            }

            j++;

            maxFreq = 1;
            maxFreqAbs = 1;

            //Obtem as expressoes da consulta presentes no titulo do documento
            String text = titulo.toLowerCase();
    		Pattern p;
    		Matcher m;
    		for (String exp : expressoesConsulta) {
    			if (!exp.trim().equals("")) {
	    			p = Pattern.compile("\\b"+exp+"\\b++");
	    			m = p.matcher(text);
	    			
	    			while (m.find()) {
		                if (!hst.testaStopWords(exp)) {
		                    
		                	//Adiciona na hash o token e o numero do artigo que o token pertence
		                    maxFreq = ht.put(exp, j, maxFreq, getPreProcessaDoc(titulo));
		                }
	    			}    			
	    			m.reset();    			
	    		}
    		}
    		
            //Obtem as expressoes da consulta presentes no abstract do documento
            text = getResultAbsKey(arrayDocs[i]).toLowerCase();
    		for (String exp : expressoesConsulta) {
    			if (!exp.trim().equals("")) {
	    			p = Pattern.compile("\\b"+exp+"\\b++");
	    			m = p.matcher(text);
	    		
	    			while (m.find()) {
	    				
		                if (!hst.testaStopWords(exp)) {
		                    
		                	//Adiciona na hash o token e o numero do artigo que o token pertence
		                	maxFreqAbs = ht.putAbs(exp, j, maxFreqAbs, getPreProcessaDoc(titulo));
		                }
	    			}    			
	    			m.reset();    			
	    		}
    		}
    		
            //Faz um pre-processamento no documento
    		arrayDocs[i] = getPreProcessaDoc(arrayDocs[i]);

    		String[] palavrasTitulo   = getTitle(arrayDocs[i]).split("[\n —]"); 
            for (String token : palavrasTitulo) {

                //transforma todos os tokens para minusculo
                token = token.toLowerCase();
                token = getPreProcessaDoc(token);

                token = token.trim();
                if (!hst.testaStopWords(token)) {
                    
                	//Adiciona na hash o token e o numero do artigo que o token pertence
                    maxFreq = ht.put(token, j, maxFreq, getPreProcessaDoc(titulo));
                }
            }
            
            //Cada posição do vetor recebe a maxima frequencia que representa o numero do documento
            vetorMaxFreq.add(maxFreq);
            
            //Obtem cada token presente no abstract do documento
            text = getResultAbsKey(arrayDocs[i]).toLowerCase();
            for (String token : text.split("[\n —]")) {

                //transforma todos os tokens para minusculo
                token = token.toLowerCase();
                token = getPreProcessaDoc(token);
                
                //Verifica se o token é uma stopWords
                token = token.trim();
                if (!hst.testaStopWords(token)) {
                                    	
                    //Adiciona na hash o token e o numero do artigo que o token pertence
                    maxFreqAbs = ht.putAbs(token, j, maxFreqAbs, getPreProcessaDoc(titulo));
                }
            }

            //Cada posição do vetor recebe a maxima frequencia que representa o numero do documento
            vetorMaxFreqAbs.add(maxFreqAbs);

        }
        
        //Atualiza o valor do número total de documentos
        setTotalDocs(j+1);
        
        //Obtem o tamanho de cada vetor dos artigos que foram excluidos
        int sizeAbs = vetorAbsExcluidos.size();
        int sizeTitle = vetorTitleExcluidos.size();
        int sizeKey = vetorKeyExcluidos.size();

        //Escreve na saida os artigos excluidos e a quantidade
        Util.escreverSaidaAbs(sizeAbs + "\n" + vetorAbsExcluidos);
        Util.escreverSaidaTitle(sizeTitle + "\n" + vetorTitleExcluidos);
        Util.escreverSaidaKey(sizeKey + "\n" + vetorKeyExcluidos);
    }

    public static String[] extrairExpressoes(String consulta){
    	consulta = consulta.toLowerCase();
		consulta = consulta.replaceAll(";", "");		
		consulta = consulta.replaceAll("\\.", "");
		consulta = consulta.replaceAll("\n", ", ");
		String[] tokens = consulta.split(",");
		List<String> expressoes = new ArrayList<String>();
		for (int i = 0; i < tokens.length; i++) {
			String aux = tokens[i].trim();
			if (aux.startsWith("\"") && aux.endsWith("\"")) {
				expressoes.add(aux.replace("\"", ""));
			}
		}
		return expressoes.toArray(new String[]{});
    }
    
    //imprimi o vetor de frequencia máxima de cada documento
    public static void printVetorMaxFreq() {

        for (int i = 0; i < vetorMaxFreq.size(); i++) {
            System.out.println("MaxFrequencia " + i + " " + getVetorMaxFreq().get(i));
        }
    }
}
